package com.then.basic.socket.core;

import java.util.Stack;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

/**
 * Created by yu on 2016/6/10.
 */
public class TcpSendThread extends HandlerThread {

    /**
     * Message Excute Task
     */
    public static final int MESSAGE_EXECUTE_TASK = 1;
    public static final int TASK_MSG_CACHE_MAX_COUNT = 10;

    /* Message Type*/
    public static final int Fold = 0;
    public static final int Raise = 1;
    public static final int Call = 2;
    public static final int Check = 3;
    public static final int AllIn = 4;
    public static final int TimeOut = 5;
    public static final int Pause = 6;
    public static final int Showdown = 7;
    public static final int Seat = 8;
    public static final int Resend = 9;
    public static final int EnterRoom = 10;
    public static final int StartGame = 11;
    public static final int EnableTakeInControl = 12;
    public static final int ChangeTakeInRange = 13;
    public static final int PermitUserTakeIn = 14;
    public static final int AddChips = 15;
    public static final int AddTime = 16;
    public static final int AddTimeOfInsurance = 17;

    // mtt message
    public static final int MttEnterRoom = 101;
    public static final int MttGetAllPeople = 102;

    // sng message
    public static final int SngEnterRoom = 301;
    public static final int SngAddTime = 302;

    // Omaha message
    public static final int OmahaEnterRoom = 401;

    // 大菠萝 message
    public static final int PineappleEnterRoom = 402;

    /**
     * DEBUG mode
     */
    private static final boolean DEBUG = TcpSendThread.DEBUG;

    /**
     * Log TAG
     */
    private static final String TAG = "TcpSendThread";

    /**
     * The s instance.
     */
    private static TcpSendThread sInstance;

    private Handler mPrivateHandler;
    private Stack<ActionTask> actionTaskCacheStack = new Stack<>();
    private UserActionCache userActionCache = new UserActionCache();

    private TcpSendThread() {
        super("TcpSendThread");
        this.start();
    }

    public static synchronized TcpSendThread getInstance() {
        if (sInstance == null) {
            sInstance = new TcpSendThread();
        }
        return sInstance;
    }

    public static synchronized void destroyInstance() {
        if (sInstance != null) {
            sInstance.quit();
            sInstance = null;
        }
    }

    private void handleTcpMsg(Message msg) {
        switch (msg.what) {
            case 0:
                break;
            case MESSAGE_EXECUTE_TASK:
                ActionTask task = (ActionTask) msg.obj;
                int roomPath = task.roompath;
                int roomID = task.roomid;
                int realRoomId = task.realRoomId;
                switch (task.action) {
                    case Fold: // 弃牌
                        userActionCache.cache(roomPath, roomID, 6, 0);
                        PokerReq.reqSendPlayerAction(6, roomPath, roomID, 0);
                        break;
                    case AllIn: // 全下
                        int chipsCount = task.wparam;
                        userActionCache.cache(roomPath, roomID, 4, chipsCount);
                        PokerReq.reqSendPlayerAction(4, roomPath, roomID, chipsCount);
                        break;
                    case Call: // 跟注
                        chipsCount = task.wparam;
                        userActionCache.cache(roomPath, roomID, 2, chipsCount);
                        PokerReq.reqSendPlayerAction(2, roomPath, roomID, chipsCount);
                        break;
                    case Check: // 看牌
                        userActionCache.cache(roomPath, roomID, 5, 0);
                        PokerReq.reqSendPlayerAction(5, roomPath, roomID, 0);
                        break;
                    case Raise: // 加注
                        chipsCount = task.wparam;
                        userActionCache.cache(roomPath, roomID, 3, chipsCount);
                        PokerReq.reqSendPlayerAction(3, roomPath, roomID, chipsCount);
                        break;
                    case TimeOut: // 倒计时完毕
                        PokerReq.reqSendPlayerAction(7, roomPath, roomID, 0);
                        break;
                    case Pause:
                        PokerReq.pauseGame(roomID, roomPath, task.wparam);
                        break;
                    case Showdown:  //亮牌
                        int pokerNum = task.wparam;
                        int isShow=task.lparam;
                        PokerReq.showDown(roomID, roomPath, pokerNum,isShow);
                        break;
                    case Seat:
                        Log.d("sit down ", "chooseSeatId=======" + task.wparam + " longitude: " + task.zparam
                                + "latitude: " + task.eparam);
                        PokerReq.reqSeatAction(task.lparam, task.wparam, roomID, roomPath,
                                task.eparam, task.xparam, false);
                        break;
                    case Resend:
                        Log.i(TAG, "UserActionCash__checkResend__actionID: " + task.wparam + "__chips:" + task.lparam + "__needResend:" + 1);
                        PokerReq.reqSendPlayerAction(task.wparam, roomPath, roomID, task.lparam);
                        break;
                    case EnterRoom:
                        PokerReq.reqEnterRoom(roomID, roomPath, task.wparam, task.lparam, task.zparam);
                        break;
                    case StartGame:
                        PokerReq.roomStartGame(roomPath, roomID);
                        break;
                    case EnableTakeInControl:
                        PokerReq.roomEnableTakeInControl(roomPath, roomID, (task.bparam));
                        break;
                    case ChangeTakeInRange:
                        PokerReq.roomChangeTakeInRange(roomID, roomPath, task.wparam, task.lparam);
                        break;
                    case PermitUserTakeIn:
                        PokerReq.roomPermitUserTakeIn(roomPath, roomID, task.wparam, task.lparam);
                        break;
                    case AddChips:
                        PokerReq.reqAddChips(roomPath, roomID, task.wparam, task.lparam,
                                task.zparam, task.eparam, task.xparam);
                        break;
                    case AddTime:
                        PokerReq.addTime(roomID, roomPath, task.wparam, task.lparam, task.zparam, false);
                        break;
                    case AddTimeOfInsurance:
                        PokerReq.addTime(roomID, roomPath, task.wparam, task.lparam, task.zparam, true);
                        break;
                    // MTT Message
                    case MttEnterRoom:
                        PokerReq.reqMttEnterRoom(roomID, roomPath, realRoomId);
                        break;
                    case MttGetAllPeople:
                        PokerReq.getMttAllPeople(roomID, roomPath);
                        break;
                    // SNG Message
                    case SngEnterRoom:
                        PokerReq.reqSngEnterRoom(roomID, roomPath);
                        break;
                    case SngAddTime:
                        PokerReq.addSngTime(roomID, roomPath, task.wparam, task.lparam, task.zparam);
                        break;
                    // Omaha message
                    case OmahaEnterRoom:
                        PokerReq.reqEnterRoomOmaha(roomID, roomPath, 1);
                        break;
                    // pineapple message
                    case PineappleEnterRoom:
                        PokerReq.reqEnterRoomPineapple(roomID, roomPath, 1);
                        break;
                    default:
                        break;
                }
                recycleActionTask(task);
                break;
            default:
                break;
        }
    }

    @Override
    protected void onLooperPrepared() {


    }

    /**
     *
     */
    public void startTask(ActionTask task) {
        if (!isAlive()) {
            try {
                start();
            } catch (IllegalThreadStateException e) {
                throw e;
            }
        }

        if (mPrivateHandler == null) {
            mPrivateHandler = new TcpSendHandler(getLooper());
        }

        mPrivateHandler.obtainMessage(MESSAGE_EXECUTE_TASK, task).sendToTarget();
    }

    public synchronized ActionTask getActionTask() {
        if (actionTaskCacheStack.isEmpty()) {
            return new ActionTask();
        } else {
            return actionTaskCacheStack.pop();
        }
    }

    public synchronized void recycleActionTask(ActionTask task) {
        if (actionTaskCacheStack.size() < TASK_MSG_CACHE_MAX_COUNT) {
            task.recycle();
            actionTaskCacheStack.push(task);
        }
    }

    public void resendFailedMessage() {
        userActionCache.checkResend();
    }

    public void sendActionSuccess() {
        userActionCache.sendActionSuccess();
    }

    public static class ActionTask {
        public int action;
        public int wparam;
        public int lparam;
        public int zparam;
        public String eparam;
        public String xparam;
        public int roomid;
        public int roompath;
        public int realRoomId;
        public boolean bparam;


        public void recycle() {
            action = 0;
            wparam = 0;
            lparam = 0;
            zparam = 0;
            roomid = 0;
            roompath = 0;
            bparam = false;
        }
    }

    public static class UserActionCache {
        int roomPath;
        int actionID = 0;
        int chips = 0;
        int roomID;
        boolean needResend = false;

        public synchronized void cache(int roomPath, int roomId, int actionID, int chips) {
            Log.i(TAG, "UserActionCash__actionID: " + actionID + "__chips:" + chips + "__needResend:" + needResend);
            if (!needResend) {//只缓存最后一条指令
                this.roomPath = roomPath;
                this.roomID = roomId;
                this.actionID = actionID;
                this.chips = chips;
                this.needResend = true;
            }
        }

        public synchronized void sendActionSuccess() {
            Log.i(TAG, "UserActionCash__sendActionSuccess");
            actionID = 0;
            chips = 0;
            needResend = false;
        }

        public void checkResend() {
            if (needResend) {
                ActionTask task = TcpSendThread.getInstance().getActionTask();
                task.action = TcpSendThread.Resend;
                task.wparam = actionID;
                task.roomid = roomID;
                task.roompath = roomPath;
                task.lparam = chips;
                TcpSendThread.getInstance().startTask(task);
            }
        }
    }

    class TcpSendHandler extends Handler {

        /**
         * Instantiates a new TcpSendHandler handler.
         *
         * @param aLpr the a lpr
         */
        TcpSendHandler(Looper aLpr) {
            super(aLpr);
        }

        /*
         * (non-Javadoc)
         *
         * @see android.os.Handler#handleMessage(android.os.Message)
         */
        @Override
        public void handleMessage(Message msg) {
            handleTcpMsg(msg);
        }
    }
}
